﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using Kamahl.Common;
using System.Net;
using System.Threading;
using KonachanChanger.Data;
using System.IO;

namespace KonachanChanger.Extensions.P2P
{
    class P2PCore
    {
        UdpClient Udp = null;
        int Port = 6938;
        IPAddress self = null;

        public static P2PCore Instance { get { return Singleton<P2PCore>.Instance; } }

        public void Init()
        {
            if (Udp != null)
                throw new InvalidOperationException("Already Initialized");
            Udp = new UdpClient(Port); //IPv4.  Not sure if this is required.
            new Thread(Listener) { IsBackground = true, Name = "UdpListener" }.Start(Udp);
            Udp.EnableBroadcast = true;
            Send(Packet.Methods.Initialized, null);
        }

        private void Send(Packet.Methods method, string data)
        {
            Send(method, data, null);
        }
        private void Send(Packet.Methods method, string data, string data2){
            var p = new Packet() { Method = method, Data = data, Data2 = data2 };
            Udp.Send(p, new IPEndPoint(IPAddress.Broadcast, 6938));
        }

        private void Listener(object obj)
        {
            IPEndPoint endpoint = null;
            while (true)
            {
                var data = Udp.Receive(ref endpoint);
                string receiveString = Encoding.Unicode.GetString(data);
                Console.WriteLine("Recieved '{0}' from {1}", receiveString, endpoint.Address.ToString());
                Packet packet = receiveString;
                if (packet.Method == Packet.Methods.Initialized && self == null)
                    self = endpoint.Address;
                if (endpoint.Address.Equals(self))
                    continue;
                switch (packet.Method)
                {
                    case Packet.Methods.Initialized:
                        break;
                    case Packet.Methods.Want:
                        try
                        {
                            var post = LocalDb.GetInstance()[Convert.ToInt32(packet.Data)];
                            if (post.Downloaded)
                                Send(Packet.Methods.Have,
                                    String.Format("{0}|{1}", post.id, Path.GetFileName(post.ImagePath))
                                    );
                        }
                        catch (KeyNotFoundException) { }
                        break;
                    case Packet.Methods.Have:
                        string id, filename;
                        packet.Data.SplitOut('|',out  id,out  filename);
                        try
                        {
                            var newpost = LocalDb.GetInstance()[Convert.ToInt32(id)];
                            if (newpost.Downloaded)
                                break;
                        }
                        catch (KeyNotFoundException) { }
                        
                        break;
                    default:
                        break;
                }
            }
        }

        internal void Request(API.post post)
        {
            Send(Packet.Methods.Want, post.id.ToString());   
        }
    }
}
